package edu.ccut.saturn.component.listener;

import edu.ccut.saturn.component.IComponentListener;
import edu.ccut.saturn.component.IDebugComponentInfo;
import edu.ccut.saturn.component.IDebugThread;
import edu.ccut.saturn.component.INodeInfo;
import edu.ccut.saturn.component.IParameterContext;
import edu.ccut.saturn.component.SaturnDebugThreadsManager;
import edu.ccut.saturn.component.impl.SaturnDebugComponentInfo;
import edu.ccut.saturn.component.impl.SaturnDebugThread;
import edu.ccut.saturn.component.utils.DateUtils;

public class DebugComponentListener implements IComponentListener {

	private SaturnDebugThreadsManager saturnDebugThreadsManager = SaturnDebugThreadsManager
			.getInstance();

	public void afterExecute(INodeInfo nodeInfo,
			IParameterContext parameterContext) {

		String name = Thread.currentThread().getName();

		IDebugThread debugThread = this.getDebugThread(name, nodeInfo);
		
		IDebugComponentInfo debugComponentInfo = debugThread.popRuntimeDebugComponetInfo();
		
		if (debugComponentInfo != null) {
			debugComponentInfo.setAfterComponentParameterContext(parameterContext);
			debugComponentInfo.setEndTime(System.currentTimeMillis());
			
			if (debugThread.isComponentInfoStackEmpty()) {
				debugThread.setEndTime(System.currentTimeMillis());
				debugThread.setDebugComponentInfo(debugComponentInfo);
				this.saturnDebugThreadsManager.removeDebugThread(debugThread);
				this.saturnDebugThreadsManager.putOverDebugThread(debugThread);
			}
		} 
	}

	public void beforeExecute(INodeInfo nodeInfo, 
			IParameterContext parameterContext) {
		
		String name = Thread.currentThread().getName();

		IDebugThread debugThread = this.getDebugThread(name, nodeInfo);
		
		IDebugComponentInfo debugComponentInfo = debugThread.getRuntimeDebugComponetInfo();
		
		IDebugComponentInfo currentDebugComponentInfo = this.createDebugComponentInfo(nodeInfo, parameterContext);
		
		if (debugComponentInfo != null) {
			debugComponentInfo.addChild(currentDebugComponentInfo);
		} 
		
		debugThread.pushRuntimeDebugComponetInfo(currentDebugComponentInfo);
	}
	
	private IDebugComponentInfo createDebugComponentInfo(INodeInfo nodeInfo,
			IParameterContext parameterContext) {

		SaturnDebugComponentInfo saturnDebugComponentInfo = new SaturnDebugComponentInfo();
		
		saturnDebugComponentInfo.setBeforeComponentParameterContext(parameterContext);
		saturnDebugComponentInfo.setNodeInfo(nodeInfo);
		saturnDebugComponentInfo.setStartTime(System.currentTimeMillis());
	
		return saturnDebugComponentInfo;
	}

	private IDebugThread getDebugThread(String threadName, INodeInfo nodeInfo) {
		String name = nodeInfo.getKey();
		
		IDebugThread debugThread = saturnDebugThreadsManager
				.getDebugThread(threadName);

		if (debugThread == null) {
			SaturnDebugThread saturnDebugThread = new SaturnDebugThread();

			long startTime = System.currentTimeMillis();
			String time = DateUtils.getSystemTime();
			saturnDebugThread.setStartTime(startTime);
			saturnDebugThread.setName(time + " [" + name + "]");

			saturnDebugThreadsManager.putDebugThread(saturnDebugThread);
			Thread.currentThread().setName(saturnDebugThread.getName());
			return saturnDebugThread;
		}

		return debugThread;
	}
}
